package Recursively;
use Mojo::Base -base;
use Data::Dumper;
#use Mojo::Base 'Exporter';
use Carp qw/confess/;
#our @EXPORT_OK = qw/ decode encode /;

my $func = {};

sub funcs{
 # Set shortcuts, for call it later via 'recursively()' method.
 # Usage funcs( 'de'=>\&Mojo::Util::decode, ... )
 
 my $se = shift;
 my %fu = @_;
 for my $n ( keys %fu ){
    $func->{ $n } = $fu{ $n };
 }
 return $se;
}

sub func{
 # Usage: func('func_name', @arg_list)
 # Call function 'func_name' from '$func' hash ref;
 my $se = shift;
 my $fu = shift;
 my $call;
 if ( !ref $fu ){
    $call = $func->{$fu} or confess "$fu - not found!";
 }
 elsif( ref $fu eq 'CODE' ){
    $call = $fu;
 }
 else{
    confess "Don't known what i can do...";
 }    
 $call->(@_);
}

sub recursively{ 
 my $se = shift;
 my $fu = shift;
 confess "Not found func '$fu'" if !$func->{$fu};
 $se->recur( $fu, @_); 
}

sub recur{
 # Recursively process scalar, arrayref and hashref values.
 # Usage: recur('shortcut',$ref)
 my $se = shift;
 #die Dumper \@_; 
 my $fu = shift;
 confess "Not found func '$fu'" if !$func->{$fu};
 if ( ! ref $_[1] ){
    #Mojo::Util::decode( $_[0],  $_[1] );
    $se->func( $fu, @_);
 }
 elsif (ref $_[1] eq 'HASH'){
    for  my $k ( keys %{$_[1]} ){
	$se->recur( $fu, $_[0],  $_[1]->{$k} );
    }
 }
 elsif (ref $_[1] eq 'ARRAY'){
    for  my $i ( 0..$#{$_[1]} ){
	$se->recur( $fu, $_[0],  $_[1]->[$i] );
    }
 }
 else{
    confess "Can't recurse for ".ref($_[1]);
 }
 return $_[1];
}


1;